package com.mademoisellegeek.carrentalsimulation.optimisation;

import com.mademoisellegeek.carrentalsimulation.Garage;
import com.mademoisellegeek.carrentalsimulation.OptimisationData;
import com.mademoisellegeek.carrentalsimulation.Optimiser;
import com.mademoisellegeek.carrentalsimulation.enums.SortMethod;
import com.mademoisellegeek.carrentalsimulation.Travel;
import com.mademoisellegeek.carrentalsimulation.Vehicle;
import java.util.ArrayList;

public class OptDepartureArrivalWithAdds extends Optimiser {

    public static int[] run(OptimisationData originalData, SortMethod method) {
        OptimisationData data = new OptimisationData(originalData);
        sortRequestList(data, method);
        for (Travel request : data.getRequestList()) {
            Vehicle availableVehicle = getAvailableVehicleOptimised(data, request.getStartTown(), request.getStartDay());
            Garage arrivalGarage = getGarageWithMostAvailableSpaces(data.getGarageDictionary(), request.getEndTown(), request.getEndDay());
            if (availableVehicle != null && arrivalGarage != null) {
                updateOptimisationData(data, availableVehicle, request, arrivalGarage);
            } else {
                String departureTown = request.getStartTown();
                int maxDistanceFromStart = data.getMaxDistanceFromTown(request.getStartTown());
                int maxDistanceFromEnd = data.getMaxDistanceFromTown(request.getEndTown());
                int startDistance = 1;
                while (startDistance < maxDistanceFromStart + 1 && availableVehicle == null) {
                    ArrayList<String> towns = data.getTownsAtDistance(startDistance, request.getStartTown());
                    departureTown = findTownWithMostAvailableVehicles(data, towns, request.getStartDay());
                    availableVehicle = getAvailableVehicleOptimised(data, departureTown, request.getStartDay());
                    startDistance++;
                }
                int endDistance = 1;
                while (endDistance < maxDistanceFromEnd + 1 && arrivalGarage == null) {
                    ArrayList<String> towns = data.getTownsAtDistance(endDistance, request.getEndTown());
                    String town = findTownWithMostAvailableSpaces(data, towns, request.getEndDay());
                    arrivalGarage = getGarageWithMostAvailableSpaces(data.getGarageDictionary(), town, request.getEndDay());
                    endDistance++;
                }
                if (availableVehicle == null | arrivalGarage == null) {
                    data.addFailedRequest(request);
                } else {
                    if (request.getEndTown().equals(arrivalGarage.getTown())) {
                        data.addAdditionalTravel(new Travel(request.getEndTown(),
                                arrivalGarage.getTown(),
                                request.getEndDay(),
                                request.getEndDay() + endDistance));
                    }
                    if (request.getStartTown().equals(departureTown)) {
                        data.addAdditionalTravel(new Travel(departureTown,
                                request.getStartTown(),
                                request.getStartDay() - startDistance,
                                request.getStartDay()));
                    }
                }
            }
        }
        return new int[]{data.getRequestList().size(),
                    getNumberOfDays(data.getRequestList()),
                    data.getFailedRequests().size(),
                    getNumberOfDays(data.getFailedRequests()),
                    data.getAdditionalTravels().size(),
                    getNumberOfDays(data.getAdditionalTravels())};
    }
}
